﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using FixSoft.CloudGround.Base;
using System.Runtime.InteropServices;
using FixSoft.Tools.FileDownloader;
using System.Windows.Forms;
using System.Text.RegularExpressions;
using System.Net.Sockets;
using FixSoft.Tools.NetworkManager;
using FixSoft.Tools.ETaskDialog;
using FixSoft.Tools.TaskDialogTools;
namespace FixSoft.CloudGround
{
    public class PictureManager
    {
        public Picture CurrentPicture;
        public List<Picture> Pictures;
        private readonly ProviderManager pmanager;
        private readonly Random rnd;
        internal readonly Downloader client;

        public delegate void PictureDownloadedHandler();
        public event PictureDownloadedHandler PictureDownloaded;
        public delegate void PictureDownloadingHandler();
        public event PictureDownloadingHandler PictureDownloading;

        private string lastKeyword;
        private int index = 0;

        public int SearchResultsCount
        {
            get { return pmanager.CurrentProvider.GetResultsCount(); }
        }

        public Provider CurrentProvider
        {
            get { return pmanager.CurrentProvider; }
            set { pmanager.CurrentProvider = value; }
        }

        public List<Provider> Providers
        {
            get { return pmanager.Providers; }
        }

        public PictureManager()
        {
            pmanager = new ProviderManager();
            pmanager.FindProviders();

            rnd = new Random(Environment.TickCount);
            client = new Downloader();
            client.Completed += ClientDownloadFileCompleted;
            client.FileDownloadFailed += ClientDownloadFileFailed;
            client.LocalDirectory = App.Path + "\\Cache";
            // client.DeleteCompletedFilesAfterCancel = true;
            LastId = -1;
        }

        // static Network NetM = new Network();
        // A method for checking the state
        public static bool IsConnected()
        {
            InternetConnection Ic = new InternetConnection();
            return Ic.IsInternetAvailable;
        }

        bool IsDownloadingList;
        public void GetPicture(string keyword)
        {
            GetPicture(keyword, App.GetFilterKeyWords(App.Settings.Filter.ToLower()));
        }
        public void GetPicture(string keyword, List<string> filterKeyword)
        {
            ThreadStart threadStarter = () =>
            {
                ChangePictureOffline();
                if (!client.IsBusy && !IsDownloadingList && IsConnected())
                {
                    App.NothingFound = false;
                    IsDownloadingList = true;
                    if (string.IsNullOrEmpty(keyword))
                    {
                        IsDownloadingList = false;
                        return;
                    }
                    if (PictureDownloading != null)
                        PictureDownloading();
                    if (Pictures == null || Pictures.Count == 0 || lastKeyword != keyword)
                        Pictures = pmanager.CurrentProvider.GetPictures(keyword, App.Settings.SkipLowRes, App.Settings.GetMaxRes, filterKeyword, App.DownloadedIds);
                    if (Pictures == null || Pictures.Count == 0)
                    {
                        NothingFound();
                        return;
                    }
                    bool IsDup;
                    IsDup = true;
                    while (IsDup)
                    {
                        if (Pictures.Count == 0)
                        {
                            NothingFound();
                            return;
                        }
                        CurrentPicture = Pictures[rnd.Next(Pictures.Count)];
                        IsDup = false;
                        foreach (string DId in App.DownloadedIds)
                        {
                            if (CurrentPicture.Id == DId)
                            {
                                Pictures.Remove(CurrentPicture);
                                IsDup = true;
                            }
                        }
                    }
                    // CurrentPicture = Pictures[index];
                    Pictures.Remove(CurrentPicture);
                    if (!Directory.Exists(App.Path + "\\Cache"))
                        Directory.CreateDirectory(App.Path + "\\Cache");
                    if (!File.Exists(App.Path + "\\Cache\\" + CurrentPicture.Id + ".jpg"))// & CurrentPicture.Url != null)
                    {
                        client.Files.Clear();
                        client.Files.Add(new Downloader.FileInfo((CurrentPicture.Url), CurrentPicture.Id + ".jpg"));//, App.Path + "\\Cache\\" + CurrentPicture.Id + ".jpg");
                        client.Start();
                    }
                    else
                    {
                        if (PictureDownloaded != null)
                            PictureDownloaded();
                        //WinAPI.SystemParametersInfo(WinAPI.SPI_SETDESKWALLPAPER, 0, App.Path + "\\Cache\\" + CurrentPicture.Id, WinAPI.SPIF_UPDATEINIFILE).ToString();
                    }

                    lastKeyword = keyword;
                    index++;
                    if (index > Pictures.Count)
                        index = 0;
                    IsDownloadingList = false;
                }
            };
            var thread = new Thread(threadStarter);
            thread.SetApartmentState(ApartmentState.STA);
            thread.Start();
        }
        void NothingFound()
        {
            if (App.Settings.ShowWarning)
            {
                ETaskDialog Td = new ETaskDialog();
                Td.CommonIcon = TaskDialogIcon.Warning;
                Td.MainInstruction = "Nothing found";
                Td.Content = "Program couldn't find any images.If this error continue to show,change your provider or keyword.";
                Td.Buttons = TaskDialogButton.OK;
                List<DialogButton > CommandLinks =new List <DialogButton>();
                CommandLinks .Add (new DialogButton (20,"Try again"));
                Td.DialogButtons = CommandLinks.ToArray();
                Td.UseCommandLinks = true;
                Td.Title = System.Windows.Forms.Application.ProductName;
                Results r=Td.Show ();
                if (r.ButtonID == 20)
                    App.CurrentApp.TimerTick(this,EventArgs .Empty );
            }
            App.Log("Nothing found.");
            App.NothingFound = true;
            if (PictureDownloaded != null)
                PictureDownloaded();
            IsDownloadingList = false;
            ChangePictureOffline();
        }

        public void ChangePictureOffline()
        {
            if (!Directory.Exists(App.Path + "\\Cache") || Directory.GetFiles(App.Path + "\\Cache").Count() == 0)
                return;
            string[] images;
            images = Directory.GetFiles(App.Path + "\\Cache");
            int CIndex;
            CIndex = LastId;
            Regex rg;
            rg = new Regex("\\.*jpg");
            while (CIndex == LastId || (CurrentPicture != null && CIndex >= 0 && GetId(images[CIndex]) == CurrentPicture.Id))
            {
                CIndex = rnd.Next(images.GetUpperBound (0)+1);
            }
            LastId = CIndex;
            App.ChangePicture(images[CIndex]);
            App.Log("Background changed offline.");
        }
        private int LastId;
        public static string GetId(string Path)
        {
            return (new FileInfo(Path).Name.Substring(0, new FileInfo(Path).Name.LastIndexOf(".")));
        }
        void ClientDownloadFileCompleted(object sender, EventArgs e)
        {
            if (PictureDownloaded != null)
                PictureDownloaded();
        }

        void ClientDownloadFileFailed(object sender, DownloadFailedEventArgs e)
        {
            App.NothingFound = true;
            if (PictureDownloaded != null)
                PictureDownloaded();
        }
        public static void ReduceQuality(string file, string destFile, int quality)
        {
            // We will store the correct image codec in this object
            ImageCodecInfo iciJpegCodec = null;
            // This will specify the image quality to the encoder
            EncoderParameter epQuality = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality);
            // Get all image codecs that are available
            ImageCodecInfo[] iciCodecs = ImageCodecInfo.GetImageEncoders();
            // Store the quality parameter in the list of encoder parameters
            EncoderParameters epParameters = new EncoderParameters(1);
            epParameters.Param[0] = epQuality;

            // Loop through all the image codecs
            for (int i = 0; i < iciCodecs.Length; i++)
            {
                // Until the one that we are interested in is found, which is image/jpeg
                if (iciCodecs[i].MimeType == "image/jpeg")
                {
                    iciJpegCodec = iciCodecs[i];
                    break;
                }
            }

            // Create a new Image object from the current file
            Image newImage = Image.FromFile(file);

            // Get the file information again, this time we want to find out the extension
            // Save the new file at the selected path with the specified encoder parameters, and reuse the same file name
            newImage.Save(destFile, iciJpegCodec, epParameters);
            newImage.Dispose();

            var info = new FileInfo(destFile);
            if (info.Length / 1024 > 256 && quality > 11)
            {
                ReduceQuality(file, destFile, quality - 10);
            }
        }
    }
}
